package dse;

import java.util.Vector;


/**
 * This class just contains information about the experiment.
 * 
 * @author Sam
 */
public class ExperimentResults {
	private double periodTime;
	private int periodsRan;

	private long messagesSent;
	private long messagesThatWereCancelled;
	private long messagesThatFailed;
	private double averageMessageDistance;
	private double averageMessageLatency;
	private double averageMessageSize;

	private double bytesSent;
	private double averageByteDistance;

	private int dataRequests;
	private int dataRequestsThatSucceeded;
	private int dataRequestsThatFailed;
	private double bytesSentForAllDataRequests;
	//private double bytesSentForAllDataRequestsThatWasNotForDataTransfer;
	private double averageDataObjectSize;
	private double averageDistanceOfObjectFromRequester;
	private double averageRequestTime;
	private double averageRequestTimeForSuccesses;
	private double averageRequestTimeForFailures;
	private long numberOfSuccessfulShareLookups;
	private long numberOfFailedShareLookups;
	private long dataObjectsFoundCached;

	//private int bloomFilterRefreshes;
	//private int bloomFilterRefreshesThatSucceeded;
	//private int bloomFilterRefreshesThatFailed;
	//private double bytesSentForAllBloomFilterRefreshes;
	
	//private int dataObjectCacheRequests;
	//private int dataObjectCacheRequestsThatSucceeded;
	//private int dataObjectCacheRequestsThatFailed;
	//private double bytesSentForAllDataObjectCaching;
	//private double bytesSentForDataObjectCachingThatWereRequestUpdates;
	//private double bytesSentForDataObjectCachingThatWereForDataTransfer;
	//private int updateSuperNodeAboutRequestsCount;
	//private double averageCachedDataObjectSize;
	
	private int dataUpdates;
	private int dataUpdatesThatSucceeded;
	private int dataUpdatesThatFailed;
	private double averageUpdateTime;
	private double averageUpdateTimeForSuccesses;
	private double averageUpdateTimeForFailures;
	private double bytesSentForAllDataUpdates;
	
	private int svr;
	private int svrFinish;
	private double averageSvrTime;
	private double bytesSentForAllSvr;
	
	/*private long oneShareRequests;
	private long oneShareRequestsThatSucceeded;
	private long oneShareRequestsThatFailed;
	private double averageOneShareRequestsTime;
	private double averageOneShareRequestsTimeForSuccesses;
	private double averageOneShareRequestsTimeForFailures;*/
	private double avgSpaceCost;
	private double maxSpaceCost;

	private int tranxNumberRequestMoreShares;
	private int tranxNumberRequestPreviousShares;
	private int totalTimesForRequestMoreShares;
	private int totalTimesForRequestPreviousShares;
	private int tranxNumberRequestOneRound;
	private double totalTimeOneRound;
	private double totalTimeMoreRound;
	private int tranxNumberOneInMoreRound;
	private double totalTimeOneInMoreRound;
	
	private int totalConcurrentUpdateTimes;
	private int totalConcurrentUpdateReadTimes;	
	//new add
	private double rDuration;
	private double uDuration;
	private int queueSize;
	
	private int shareHistorySize;
	
	private int maxUpdates;
	private int maxUpdatesThatSucceeded;
	private int maxUpdatesThatFailed;
	private double averageMaxUpdateTime;
	private double averageMaxUpdateTimeForSuccesses;
	private double averageMaxUpdateTimeForFailures;
	private int maxRequests;
	private int maxRequestsThatSucceeded;
	private int maxRequestsThatFailed;
	private double averageMaxRequestTime;
	private double averageMaxRequestTimeForSuccesses;
	private double averageMaxRequestTimeForFailures;
	
	private int maxTranxRequestMoreShares;
	private int maxTranxRequestPreviousShares;
	private int maxTimesForRequestMoreShares;
	private int maxTimesForRequestPreviousShares;

	public void setAverageByteDistance (double averageByteDistance) {
		this.averageByteDistance = averageByteDistance;
	}

	public void setAverageDataObjectSize (double averageDataObjectSize) {
		this.averageDataObjectSize = averageDataObjectSize;
	}

	public void setAverageDistanceOfObjectFromRequester (
			double averageDistanceOfObjectFromRequester) {
		this.averageDistanceOfObjectFromRequester = averageDistanceOfObjectFromRequester;
	}

	public void setAverageMessageDistance (double averageMessageDistance) {
		this.averageMessageDistance = averageMessageDistance;
	}

	public void setAverageMessageLatency (double averageMessageLatency) {
		this.averageMessageLatency = averageMessageLatency;
	}

	public void setAverageMessageSize (double averageMessageSize) {
		this.averageMessageSize = averageMessageSize;
	}

	public void setAverageRequestTime (double averageRequestTime) {
		this.averageRequestTime = averageRequestTime;
	}

	public void setAverageRequestTimeForFailures (
			double averageRequestTimeForFailures) {
		this.averageRequestTimeForFailures = averageRequestTimeForFailures;
	}

	public void setAverageRequestTimeForSuccesses (
			double averageRequestTimeForSuccesses) {
		this.averageRequestTimeForSuccesses = averageRequestTimeForSuccesses;
	}

	/*public void setBloomFilterRefreshes (int bloomFilterRefreshes) {
		this.bloomFilterRefreshes = bloomFilterRefreshes;
	}

	public void setBloomFilterRefreshesThatFailed (
			int bloomFilterRefreshesThatFailed) {
		this.bloomFilterRefreshesThatFailed = bloomFilterRefreshesThatFailed;
	}

	public void setBloomFilterRefreshesThatSucceeded (
			int bloomFilterRefreshesThatSucceeded) {
		this.bloomFilterRefreshesThatSucceeded = bloomFilterRefreshesThatSucceeded;
	}
	
	public void setBytesSentForAllBloomFilterRefreshes (
			double bytesSentForAllBloomFilterRefreshes) {
		this.bytesSentForAllBloomFilterRefreshes = bytesSentForAllBloomFilterRefreshes;
	}

	public void setBytesSentForAllDataObjectCaching (
			double bytesSentForAllDataObjectCaching) {
		this.bytesSentForAllDataObjectCaching = bytesSentForAllDataObjectCaching;
	}
	
	public void setBytesSentForDataObjectCachingThatWereForDataTransfer (
			double bytesSentForDataObjectCachingThatWereForDataTransfer) {
		this.bytesSentForDataObjectCachingThatWereForDataTransfer = bytesSentForDataObjectCachingThatWereForDataTransfer;
	}

	public void setBytesSentForDataObjectCachingThatWereRequestUpdates (
			double bytesSentForDataObjectCachingThatWereRequestUpdates) {
		this.bytesSentForDataObjectCachingThatWereRequestUpdates = bytesSentForDataObjectCachingThatWereRequestUpdates;
	}

	public void setDataObjectCacheRequests (int dataObjectCacheRequests) {
		this.dataObjectCacheRequests = dataObjectCacheRequests;
	}

	public void setDataObjectCacheRequestsThatFailed (
			int dataObjectCacheRequestsThatFailed) {
		this.dataObjectCacheRequestsThatFailed = dataObjectCacheRequestsThatFailed;
	}

	public void setDataObjectCacheRequestsThatSucceeded (
			int dataObjectCacheRequestsThatSucceeded) {
		this.dataObjectCacheRequestsThatSucceeded = dataObjectCacheRequestsThatSucceeded;
	}

	public void setDataObjectsFoundCached (long dataObjectsFoundCached) {
		this.dataObjectsFoundCached = dataObjectsFoundCached;
	}
	
	public void setUpdateSuperNodeAboutRequestsCount (
			int updateSuperNodeAboutRequestsCount) {
		this.updateSuperNodeAboutRequestsCount = updateSuperNodeAboutRequestsCount;
	}

	public void setAverageCachedDataObjectSize (double averageCachedDataObjectSize) {
		this.averageCachedDataObjectSize = averageCachedDataObjectSize;
	}
	*/

	public void setBytesSent (double bytesSent) {
		this.bytesSent = bytesSent;
	}

	public void setBytesSentForAllDataRequests (
			double bytesSentForAllDataRequests) {
		this.bytesSentForAllDataRequests = bytesSentForAllDataRequests;
	}

	/*public void setBytesSentForAllDataRequestsThatWasNotForDataTransfer (
			double bytesSentForAllDataRequestsThatWasNotForDataTransfer) {
		this.bytesSentForAllDataRequestsThatWasNotForDataTransfer = bytesSentForAllDataRequestsThatWasNotForDataTransfer;
	}*/
	
	public void setDataRequests (int dataRequests, int dataRequestsThatFailed, 
			int dataRequestsThatSucceeded) {
		this.dataRequests = dataRequests;
		this.dataRequestsThatFailed = dataRequestsThatFailed;
		this.dataRequestsThatSucceeded = dataRequestsThatSucceeded;
	}

	public void setMessagesSent (long messagesSent) {
		this.messagesSent = messagesSent;
	}

	public void setMessagesThatFailed (long messagesThatFailed) {
		this.messagesThatFailed = messagesThatFailed;
	}

	public void setMessagesThatWereCancelled (long messagesThatWereCancelled) {
		this.messagesThatWereCancelled = messagesThatWereCancelled;
	}

	public void setNumberOfFailedShareLookups (long numberOfFailedShareLookups) {
		this.numberOfFailedShareLookups = numberOfFailedShareLookups;
	}

	public void setNumberOfSuccessfulShareLookups (
			long numberOfSuccessfulShareLookups) {
		this.numberOfSuccessfulShareLookups = numberOfSuccessfulShareLookups;
	}

	public void setPeriodsRan (int periodsRan) {
		this.periodsRan = periodsRan;
	}

	public void setPeriodTime (double periodTime) {
		this.periodTime = periodTime;
	}
	
	public void setDataUpdates (int dataUpdates, int dataUpdatesThatFailed, 
			int dataUpdatesThatSucceeded) {
		this.dataUpdates = dataUpdates;
		this.dataUpdatesThatFailed = dataUpdatesThatFailed;
		this.dataUpdatesThatSucceeded = dataUpdatesThatSucceeded;
	}
	
	public void setAverageUpdateTime (double averageUpdateTime) {
		this.averageUpdateTime = averageUpdateTime;
	}

	public void setAverageUpdateTimeForFailures (
			double averageUpdateTimeForFailures) {
		this.averageUpdateTimeForFailures = averageUpdateTimeForFailures;
	}

	public void setAverageUpdateTimeForSuccesses (
			double averageUpdateTimeForSuccesses) {
		this.averageUpdateTimeForSuccesses = averageUpdateTimeForSuccesses;
	}
	
	public void setBytesSentForAllDataUpdates (
			double bytesSentForAllDataUpdates) {
		this.bytesSentForAllDataUpdates = bytesSentForAllDataUpdates;
	}
	
	public void setSvr (int s, int sf) {
		this.svr = s;
		this.svrFinish = sf;
	}
	
	public void setAverageSvrTime (double averageSvrTime) {
		this.averageSvrTime = averageSvrTime;
	}
	
	public void setBytesSentForAllSvr (
			double bytesSentForAllSvrs) {
		this.bytesSentForAllSvr = bytesSentForAllSvrs;
	}
		
	public void setMaxUpdates (int maxUpdates, int maxUpdatesThatFailed,
			int maxUpdatesThatSucceeded) {
		this.maxUpdates = maxUpdates;
		this.maxUpdatesThatFailed = maxUpdatesThatFailed;
		this.maxUpdatesThatSucceeded = maxUpdatesThatSucceeded;
	}
	
	public void setAverageMaxUpdateTime (double averageMaxUpdateTime) {
		this.averageMaxUpdateTime = averageMaxUpdateTime;
	}

	public void setAverageMaxUpdateTimeForFailures (
			double averageMaxUpdateTimeForFailures) {
		this.averageMaxUpdateTimeForFailures = averageMaxUpdateTimeForFailures;
	}

	public void setAverageMaxUpdateTimeForSuccesses (
			double averageMaxUpdateTimeForSuccesses) {
		this.averageMaxUpdateTimeForSuccesses = averageMaxUpdateTimeForSuccesses;
	}
	
	public void setMaxRequests (int maxRequests, int maxRequestsThatFailed, 
			int maxRequestsThatSucceeded) {
		this.maxRequests = maxRequests;
		this.maxRequestsThatFailed = maxRequestsThatFailed;
		this.maxRequestsThatSucceeded = maxRequestsThatSucceeded;
	}
	
	public void setAverageMaxRequestTime (double averageMaxRequestTime) {
		this.averageMaxRequestTime = averageMaxRequestTime;
	}

	public void setAverageMaxRequestTimeForFailures (
			double averageMaxRequestTimeForFailures) {
		this.averageMaxRequestTimeForFailures = averageMaxRequestTimeForFailures;
	}

	public void setAverageMaxRequestTimeForSuccesses (
			double averageMaxRequestTimeForSuccesses) {
		this.averageMaxRequestTimeForSuccesses = averageMaxRequestTimeForSuccesses;
	}
	
	/*public void setAverageOneShareRequestsTime(double aosrt)
	{
		//this.averageOneShareRequestsTime = aosrt;
	}
	
	public void setAverageOneShareRequestsTimeForFailures(double aosrtff)
	{
		//this.averageOneShareRequestsTimeForFailures = aosrtff;
	}

	public void setAverageOneShareRequestsTimeForSuccesses(double aosrtfs)
	{
		//this.averageOneShareRequestsTimeForSuccesses = aosrtfs;
	}
	
	public void setOneShareRequests(int oneShareRequestsCount)
	{
		//this.oneShareRequests = oneShareRequestsCount;
	}
	
	public void setOneShareRequestsThatSucceeded(int oneShareRequestsSuccessCount)
	{
		//this.oneShareRequestsThatSucceeded = oneShareRequestsSuccessCount;
	}
	
	public void setOneShareRequestsThatFailed(int oneShareRequestsFailure)
	{
		//this.oneShareRequestsThatFailed = oneShareRequestsFailure;
	}*/
	
	public void setSpaceCost(double[] cost)
	{
		avgSpaceCost = cost[0]/1000;
		maxSpaceCost = cost[1]/1000;
	}
	
	public void setRequestMoreShares(int rms, int tn){
		this.totalTimesForRequestMoreShares = rms;
		this.tranxNumberRequestMoreShares = tn;
	}
	
	public void setRequestPreviousShares(int rps, int tn, int or){
		this.totalTimesForRequestPreviousShares = rps;
		this.tranxNumberRequestPreviousShares = tn;
		this.tranxNumberRequestOneRound = or;
	}
	
	public void setOneInMore(int trx, double tom){
		this.tranxNumberOneInMoreRound = trx;
		this.totalTimeOneInMoreRound = tom;
	}
	
	public void setMaxRequestMoreShares(int rms, int tn){
		this.maxTimesForRequestMoreShares = rms;
		this.maxTranxRequestMoreShares = tn;
	}
	
	public void setMaxRequestPreviousShares(int rps, int tn){
		this.maxTimesForRequestPreviousShares = rps;
		this.maxTranxRequestPreviousShares = tn;
	}
	
	public void setTotalTimeForRound(double oneround, double moreround){
		this.totalTimeOneRound = oneround;
		this.totalTimeMoreRound = moreround;
	}
	
	public void setTotalConcurrentTimes(int uu, int ur){
		this.totalConcurrentUpdateTimes = uu;
		this.totalConcurrentUpdateReadTimes = ur;
	}
	
	public void setReadUpdateDuration(double rDur, double uDur){
		this.rDuration = rDur;
		this.uDuration = uDur;
	}
	
	public void setQueueSize(int qs){
		this.queueSize = qs;
	}
	
	public void setShareHistorySize(int size){
		this.shareHistorySize = size;
	}
	
	//two level order
	private double averageUpdatePropagationTime;
	
	public void setTLUpdatePropagation(int c, double t){
		this.averageUpdatePropagationTime = t/c;
	}
	
	public String toString (
			TestType type,
			Network network, 
			Vector<DataObject> dataObjects,			
			double timeTook
			)
	{
		double expTime = periodTime*periodsRan;
				
		StringBuilder builder = new StringBuilder (800);
		builder.append("Results:\n");
		builder.append("Actual time experiment took to run:");
		builder.append(StringUtil.timeString(timeTook));
		builder.append("\n");
		
		// Period information
		builder.append("Periods: " + periodsRan);
		builder.append(
				", Period Length: " + StringUtil.timeString(periodTime) + "\n"
				); 
		builder.append("Time simulated: " + StringUtil.timeString(expTime));
		builder.append("\n");
		builder.append("\n");
		
		int up = 0;
		int down = 0;
		for (Node n : network.nodes()) 
			if (n.isUp()) 
				up++; 
			else if (n.isDown())
				down++;
		builder.append(
				"Nodes: " + network.nodeCount() + ".  At end of test " + 
				up + " up " + down + " down. \n"
				);
		if (type == TestType.Mixed || type == TestType.MixedWithoutShares || 
				type==TestType.ClusterWithShares || type==TestType.TLA) {
			builder.append("Clusters: " + network.clusterCount() + "\n");
			double cs = 0;
			for (Cluster c : network.clusters()) 
				cs += c.size()/(double)network.clusterCount();
			builder.append("Average cluster size: " + cs + "\n");
			double dist = 0;
			for (Cluster c : network.clusters())
				for (Node n : c.nodes()) 
					dist += (n.distanceTo(c.superNode()))/network.nodeCount();
			builder.append("Average node to super node distance: " + 
					StringUtil.distanceString(dist) + "\n"
					);
		}
		
		builder.append("Data Objects: " + dataObjects.size());
		double ds = 0;
		for (DataObject d : dataObjects) 
			ds += d.size();
		builder.append(
				"\nAverage Data Object Size : " + 
				StringUtil.byteString((ds/dataObjects.size()))
				);
		
		builder.append("\n");		
		builder.append("\n");
		builder.append("\n");
				
		// Total Message Info
		
		builder.append("Messages Sent: " + messagesSent + "\n");
		builder.append(messagesSent/(1.0*periodsRan) + " avg msgs/period, ");
		builder.append(
				messagesSent/(1.0*network.nodeCount()) + " avg msgs/node "
				);
		builder.append("\nSuccessful Msgs: ");
		builder.append(
				messagesSent-messagesThatFailed-messagesThatWereCancelled
				);
		builder.append(", Failed Msgs: " + messagesThatFailed);
		builder.append(", Cancelled Msgs: " + messagesThatWereCancelled);
		builder.append("\n");
		builder.append(
				"Avg Msg Size: " + StringUtil.byteString(averageMessageSize)
				);
		builder.append("\n");
		builder.append(
				"Avg Msg Distance: " + 
				StringUtil.distanceString(averageMessageDistance)
				);
		builder.append("\n");
		builder.append(
				"Avg Msg Latency: " + 
				StringUtil.timeString(averageMessageLatency)
				);
		
		builder.append("\n");
		builder.append("\n");
		builder.append("\n");

		// Total Bytes Info
		builder.append(
				"Bytes Transferred: " + StringUtil.byteString(bytesSent) + " "
				);		
		builder.append("\n");
		builder.append(StringUtil.byteString(bytesSent/periodsRan)
				+ " avg bytes/period, ");
		builder.append(
				StringUtil.byteString(bytesSent/network.nodeCount())+ 
				" avg bytes/node, "
				);
		builder.append(
				StringUtil.byteString(bytesSent/network.nodeCount()/periodsRan)
				+ " avg bytes/node/period "
				);
		builder.append("\n");
		builder.append(
				"Avg Distance Byte Transferred: " + 
				StringUtil.distanceString(averageByteDistance)
				);		
		builder.append("\n");
		
		builder.append("\n");
		builder.append("\n");

		builder.append("Bytes Sent For All Data Requests: ");
		builder.append(StringUtil.byteString(bytesSentForAllDataRequests));
		builder.append("\n");
		builder.append(
				StringUtil.byteString(bytesSentForAllDataRequests/dataRequests)
				);
		builder.append(" avg bytes/data request");
		builder.append("\n");
		/*builder.append("Bytes Sent That Were Not Part of Data Transfers: ");
		builder.append(StringUtil.byteString(
				bytesSentForAllDataRequestsThatWasNotForDataTransfer
				));
		builder.append("\n");*/
		builder.append("Bytes Sent For All Data Updates: ");
		builder.append(StringUtil.byteString(bytesSentForAllDataUpdates));
		builder.append("\n");
		builder.append(
				StringUtil.byteString(bytesSentForAllDataUpdates/dataUpdates)
				);
		builder.append(" avg bytes/data update");
		builder.append("\n");
		builder.append("Bytes Sent For All SVRs: ");
		builder.append(StringUtil.byteString(bytesSentForAllSvr));
		builder.append("\n");
		builder.append(
				StringUtil.byteString(bytesSentForAllSvr/svr)
				);
		builder.append(" avg bytes/SVR");
		builder.append("\n");
		
		// Data Request Info
		builder.append("Data Requests Made: " + dataRequests);		
		builder.append(", " + (dataRequestsThatSucceeded));
		builder.append(" successes, ");
		builder.append(dataRequestsThatFailed + " failures");
		builder.append("\n");
		/**Add***/
		builder.append("Data Updates Made: " + dataUpdates);		
		builder.append(", " + (dataUpdatesThatSucceeded));
		builder.append(" successes, ");
		builder.append(dataUpdatesThatFailed + " failures");
		builder.append("\n");
		builder.append("SVR Made: " + svr);
		builder.append(", " + svrFinish);
		builder.append(" finished");
		builder.append("\n");

		/**Add End***/
		
		builder.append(
				"Avg Data Request Latency: " + 
				StringUtil.timeString(averageRequestTime)
				);
		builder.append(", " + 
				StringUtil.timeString(averageRequestTimeForSuccesses)
				);
		builder.append(" for successes, ");
		builder.append(StringUtil.timeString(averageRequestTimeForFailures));
		builder.append(" for failures\n");
		
		/**New add**/
		builder.append("Average read duration is: ");
		builder.append(this.rDuration/this.dataRequests);
		builder.append("\n");
		/**New add**/
		
		builder.append("Total data requests ask more shares: "); 
		builder.append(this.tranxNumberRequestMoreShares);
		builder.append(". The rate is: ");
		builder.append(String.format("%09.6f", this.tranxNumberRequestMoreShares*1.0/this.dataRequests));
		builder.append("\n");
		
		builder.append("Total times ask more shares: ");
		builder.append(this.totalTimesForRequestMoreShares);
		builder.append(". Average times for one data request is ");
		builder.append(String.format("%09.6f", this.totalTimesForRequestMoreShares*1.0/this.dataRequests));
		builder.append("\n");
		
		builder.append("Total data requests ask previous shares: "); 
		builder.append(this.tranxNumberRequestPreviousShares);
		builder.append(". The rate is: ");
		builder.append(String.format("%09.6f, ", this.tranxNumberRequestPreviousShares*1.0/this.dataRequestsThatSucceeded));
		builder.append("One round Latency is: " );
		builder.append(StringUtil.timeString(this.totalTimeOneInMoreRound/this.tranxNumberOneInMoreRound));
		builder.append(", Average Latency is: " );
		builder.append(StringUtil.timeString(this.totalTimeMoreRound/this.tranxNumberRequestPreviousShares));
		builder.append("\n");
		
		builder.append("Total data requests ask one round: "); 
		builder.append(this.tranxNumberRequestOneRound);
		builder.append(". The rate is: ");
		builder.append(String.format("%09.6f, ", this.tranxNumberRequestOneRound*1.0/this.dataRequestsThatSucceeded));
		builder.append("Average Latency is: " );
		builder.append(StringUtil.timeString(this.totalTimeOneRound/this.tranxNumberRequestOneRound));
		builder.append("\n");
		
		builder.append("Total times ask previous shares: ");
		builder.append(this.totalTimesForRequestPreviousShares);
		builder.append(". Average times for one data request is ");
		builder.append(String.format("%09.6f", this.totalTimesForRequestPreviousShares*1.0/this.dataRequests));
		builder.append("\n");
		
		
		/**Add***/
		builder.append(
				"Avg Data Update Latency: " + 
				StringUtil.timeString(averageUpdateTime)
				);
		builder.append(", " + 
				StringUtil.timeString(averageUpdateTimeForSuccesses)
				);
		builder.append(" for successes, ");
		builder.append(StringUtil.timeString(averageUpdateTimeForFailures));
		builder.append(" for failures\n");	
		if(type==TestType.TwoLevelDhtShare || type==TestType.TLA){
			builder.append(
					"Avg Data Update Propagation Latency: " + 
					StringUtil.timeString(averageUpdatePropagationTime));
			builder.append("\n");
		}
		builder.append(
				"Avg SVR Latency: " + 
				StringUtil.timeString(averageSvrTime)
				);
		builder.append("\n");
		builder.append("\n");
		
		
		builder.append("For the most frequently accessed data object: \n");
		builder.append("Max: Requests Made: " + maxRequests);		
		builder.append(", " + (maxRequestsThatSucceeded));
		builder.append(" successes, ");
		builder.append(maxRequestsThatFailed + " failures");
		builder.append("\n");
		builder.append("Max: Updates Made: " + maxUpdates);		
		builder.append(", " + (maxUpdatesThatSucceeded));
		builder.append(" successes, ");
		builder.append(maxUpdatesThatFailed + " failures");
		builder.append("\n");
		builder.append(
				"Max: Avg Request Latency: " + 
				StringUtil.timeString(averageMaxRequestTime)
				);
		builder.append(", " + 
				StringUtil.timeString(averageMaxRequestTimeForSuccesses)
				);
		builder.append(" for successes, ");
		builder.append(StringUtil.timeString(averageMaxRequestTimeForFailures));
		builder.append(" for failures\n");		
		builder.append("Max: Total requests ask more shares: "); 
		builder.append(this.maxTranxRequestMoreShares);
		builder.append(". The rate is: ");
		builder.append(String.format("%09.6f", this.maxTranxRequestMoreShares*1.0/this.maxRequestsThatSucceeded));
		builder.append("\n");
		
		builder.append("Max: max times ask more shares: ");
		builder.append(this.maxTimesForRequestMoreShares);
		builder.append(".\n");
		
		builder.append("Max: Total requests ask previous shares: "); 
		builder.append(this.maxTranxRequestPreviousShares);
		builder.append(". The rate is: ");
		builder.append(String.format("%09.6f", this.maxTranxRequestPreviousShares*1.0/this.maxRequestsThatSucceeded));
		builder.append("\n");
		builder.append("Max: max times ask previous shares: ");
		builder.append(this.maxTimesForRequestPreviousShares);
		builder.append(".\n");
		builder.append(
				"Max: Avg Update Latency: " + 
				StringUtil.timeString(averageMaxUpdateTime)
				);
		builder.append(", " + 
				StringUtil.timeString(averageMaxUpdateTimeForSuccesses)
				);
		builder.append(" for successes, ");
		builder.append(StringUtil.timeString(averageMaxUpdateTimeForFailures));
		builder.append(" for failures\n");
		
		
		/**New add**/
		builder.append("Average update duration is: ");
		builder.append(this.uDuration/this.dataUpdates);
		builder.append("\n");
		/**New add**/
		
		builder.append("Total concurrent update occurs ");
		builder.append(this.totalConcurrentUpdateTimes);
		builder.append(" times\n");
		builder.append("Total concurrent update and read occurs ");
		builder.append(this.totalConcurrentUpdateReadTimes);
		builder.append(" times\n");
		
		
		builder.append("Final Average Space Cost: ");
		builder.append(avgSpaceCost);
		builder.append("K\n");
		builder.append("Final Maximum Space Cost: ");
		builder.append(maxSpaceCost);
		builder.append("K\n");
		
		
		builder.append("Maximum share history size: ");
		builder.append(this.shareHistorySize);
		builder.append("\n");
		builder.append("Maximum request queue size: ");
		builder.append(this.queueSize);
		builder.append("\n");
		
		/*builder.append("Resume Shares Requests Made: " + oneShareRequests);		
		builder.append(", " + (oneShareRequestsThatSucceeded));
		builder.append(" successes, ");
		builder.append(oneShareRequestsThatFailed + " failures");
		builder.append("\n");
		builder.append(
				"Avg Resume Share Requests Latency: " + 
				StringUtil.timeString(averageOneShareRequestsTime)
				);
		builder.append(", " + 
				StringUtil.timeString(averageOneShareRequestsTimeForSuccesses)
				);
		builder.append(" for successes, ");
		builder.append(StringUtil.timeString(averageOneShareRequestsTimeForFailures));
		builder.append(" for failures\n");*/
		/**Add End***/
		
		builder.append("Avg Distance From Requester to Found Data Object: ");
		builder.append(
				StringUtil.distanceString(averageDistanceOfObjectFromRequester)
				);		
		builder.append("\n");
		builder.append("Avg Data Object Size: ");
		builder.append(StringUtil.byteString(averageDataObjectSize));
		builder.append(" bytes\n");
		
		if (type == TestType.Mixed || type == TestType.DhtWithShares || type==TestType.ClusterWithShares ||
				type == TestType.DVS || type == TestType.UVN || type == TestType.DhtShareWithVersion3) {
			builder.append("Number of Successful Share Lookups: ");
			builder.append(numberOfSuccessfulShareLookups);
			builder.append("\n");
			builder.append("Number of Failed Share Lookups: ");
			builder.append(numberOfFailedShareLookups);
			builder.append("\nShare Lookup Success Rate: ");
			long totalLps = 
				numberOfSuccessfulShareLookups + numberOfFailedShareLookups;
			if (numberOfSuccessfulShareLookups == 0)
				builder.append("100");
			else
				builder.append((100.0*numberOfSuccessfulShareLookups)/totalLps);
			builder.append("%\n");
		}
		
		builder.append("Data Objects Found In Host Clusters: ");
		builder.append(
				dataRequestsThatSucceeded - dataObjectsFoundCached
				);
		builder.append("\n");

		/*if (type == TestType.Mixed || type==TestType.MixedWithoutShares) {
			builder.append("Data Objects Found In Cached Clusters: ");
			builder.append(dataObjectsFoundCached);
			
			builder.append("\n");
			builder.append("\n");
			builder.append("\n");
			
			// Data Request Info
			builder.append("Bloom Filter Refreshes: " + bloomFilterRefreshes);		
			builder.append(", " + (bloomFilterRefreshesThatSucceeded));
			builder.append(" successes, ");
			builder.append(bloomFilterRefreshesThatFailed + " failures");
			builder.append("\n");
			builder.append("Bytes Sent For All Data Requests: ");
			builder.append(
					StringUtil.byteString(bytesSentForAllBloomFilterRefreshes)
					);
			
			builder.append("\n");
			builder.append("\n");
			builder.append("\n");
	
			// Data Request Info
			builder.append("Caching Requests: " + dataObjectCacheRequests);		
			builder.append(", " + (dataObjectCacheRequestsThatSucceeded));
			builder.append(" successes, ");
			builder.append(dataObjectCacheRequestsThatFailed + " failures");
			builder.append("\nTimes super nodes were updated with local");
			builder.append("requests:");
			builder.append(updateSuperNodeAboutRequestsCount);
			builder.append("\n");
			builder.append("Bytes Sent For All Cache Requests: ");
			builder.append(
					StringUtil.byteString(bytesSentForAllDataObjectCaching)
					);
			builder.append("\n");
			builder.append(
					"Bytes Sent To Update Super Nodes About Local Requests: "
					);
			
			builder.append(
					StringUtil.byteString(
							bytesSentForDataObjectCachingThatWereRequestUpdates
							)
					);
			builder.append("\n");
			builder.append(
					"Bytes Sent That Were For Data Transfer: "
					);
			builder.append(
					StringUtil.byteString(
							bytesSentForDataObjectCachingThatWereForDataTransfer
							)
					);
			builder.append("\n");
			builder.append("Average Size of Cached Data Objects ");
			if (type == TestType.Mixed || type==TestType.DhtWithShares)
				builder.append("(shares dl * share size): ");
			builder.append(StringUtil.byteString(averageCachedDataObjectSize));
		}*/
					
		return builder.toString();
	}
}
